﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace HB.Base
{
    /// <summary>
    /// Expression合成，用于动态条件，可用于数据筛选
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ExpressionFilter<T> : ExpressionVisitor
    {
        Expression<Func<T, bool>> _Filter;
        Dictionary<ParameterExpression, ParameterExpression> map;
        /// <summary>
        /// 初始化基本条件
        /// </summary>
        /// <param name="BaseFilter"></param>
        public ExpressionFilter(bool BaseFilter = true)
        {
            _Filter = (T) => BaseFilter;
        }
        Func<T, bool> Func
        {
            get { return _Filter.Compile(); }
            set { }
        }
        Expression<Func<T, bool>> Expressions
        {
            get { return _Filter; }
            set { }
        }

        public ExpressionFilter<T> Or(Expression<Func<T, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.OrElse);
            return this;
        }

        public ExpressionFilter<T> And(Expression<Func<T, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.AndAlso);return this;
        }
        public ExpressionFilter<T> OrIf(bool condition, Expression<Func<T, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.OrElse);
            }
            return this;
        }
        public ExpressionFilter<T> AndIf(bool condition, Expression<Func<T, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.AndAlso);
            }
            return this;
        }

        public static implicit operator Func<T, bool>(ExpressionFilter<T> filter)
        {
            return filter.Func;
        }
        public static implicit operator Expression<Func<T, bool>>(ExpressionFilter<T> filter)
        {
            return filter.Expressions;
        }
        private Expression<TT> Compose<TT>(Expression<TT> first, Expression<TT> second, Func<Expression, Expression, Expression> merge)
        {
            map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = Visit(second.Body);
            return Expression.Lambda<TT>(merge(first.Body, secondBody), first.Parameters);
        }
        protected override Expression VisitParameter(ParameterExpression p)
        {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement))
            {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }
    public class ExpressionFilter<T, T2> : ExpressionVisitor
    {
        Expression<Func<T, T2, bool>> _Filter;
        Dictionary<ParameterExpression, ParameterExpression> map;
        public ExpressionFilter(bool BaseFilter = true)
        {
            _Filter = (T, T2) => BaseFilter;
        }
        Func<T, T2, bool> Func
        {
            get { return _Filter.Compile(); }
            set { }
        }
        Expression<Func<T, T2, bool>> Expressions
        {
            get { return _Filter; }
            set { }
        }

        public ExpressionFilter<T, T2> Or(Expression<Func<T, T2, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.OrElse);return this;

        }
        public ExpressionFilter<T, T2> And(Expression<Func<T, T2, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.AndAlso); return this;
        }
        public ExpressionFilter<T, T2> OrIf(bool condition, Expression<Func<T, T2, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.OrElse);
            }
            return this;
        }
        public ExpressionFilter<T, T2> AndIf(bool condition, Expression<Func<T, T2, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.AndAlso);
            }
            return this;
        }
        public static implicit operator Func<T, T2, bool>(ExpressionFilter<T, T2> filter)
        {
            return filter.Func;
        }
        public static implicit operator Expression<Func<T, T2, bool>>(ExpressionFilter<T, T2> filter)
        {
            return filter.Expressions;
        }
        private Expression<TT> Compose<TT>(Expression<TT> first, Expression<TT> second, Func<Expression, Expression, Expression> merge)
        {
            map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = Visit(second.Body);
            return Expression.Lambda<TT>(merge(first.Body, secondBody), first.Parameters);
        }
        protected override Expression VisitParameter(ParameterExpression p)
        {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement))
            {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }
    public class ExpressionFilter<T, T2, T3> : ExpressionVisitor
    {
        Expression<Func<T, T2, T3, bool>> _Filter;
        Dictionary<ParameterExpression, ParameterExpression> map;
        public ExpressionFilter(bool BaseFilter = true)
        {
            _Filter = (T, T2, T3) => BaseFilter;
        }
        Func<T, T2, T3, bool> Func
        {
            get { return _Filter.Compile(); }
            set { }
        }
        Expression<Func<T, T2, T3, bool>> Expressions
        {
            get { return _Filter; }
            set { }
        }

        public ExpressionFilter<T, T2, T3> Or(Expression<Func<T, T2, T3, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.OrElse);return this;

        }
        public ExpressionFilter<T, T2, T3> And(Expression<Func<T, T2, T3, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.AndAlso); return this;
        }
        public ExpressionFilter<T, T2, T3> OrIf(bool condition, Expression<Func<T, T2, T3, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.OrElse);
            }
            return this;
        }
        public ExpressionFilter<T, T2, T3> AndIf(bool condition, Expression<Func<T, T2, T3, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.AndAlso);
            }
            return this;
        }
        public static implicit operator Func<T, T2, T3, bool>(ExpressionFilter<T, T2, T3> filter)
        {
            return filter.Func;
        }
        public static implicit operator Expression<Func<T, T2, T3, bool>>(ExpressionFilter<T, T2, T3> filter)
        {
            return filter.Expressions;
        }
        private Expression<TT> Compose<TT>(Expression<TT> first, Expression<TT> second, Func<Expression, Expression, Expression> merge)
        {
            map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = Visit(second.Body);
            return Expression.Lambda<TT>(merge(first.Body, secondBody), first.Parameters);
        }
        protected override Expression VisitParameter(ParameterExpression p)
        {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement))
            {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }
    public class ExpressionFilter<T, T2, T3, T4> : ExpressionVisitor
    {
        Expression<Func<T, T2, T3, T4, bool>> _Filter;
        Dictionary<ParameterExpression, ParameterExpression> map;
        public ExpressionFilter(bool BaseFilter = true)
        {
            _Filter = (T, T2, T3, T4) => BaseFilter;
        }
        Func<T, T2, T3, T4, bool> Func
        {
            get { return _Filter.Compile(); }
            set { }
        }
        Expression<Func<T, T2, T3, T4, bool>> Expressions
        {
            get { return _Filter; }
            set { }
        }

        public ExpressionFilter<T, T2, T3, T4> Or(Expression<Func<T, T2, T3, T4, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.OrElse);return this;

        }
        public ExpressionFilter<T, T2, T3, T4> And(Expression<Func<T, T2, T3, T4, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.AndAlso); return this;
        }
        public ExpressionFilter<T, T2, T3, T4> OrIf(bool condition, Expression<Func<T, T2, T3, T4, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.OrElse);
            }
            return this;
        }
        public ExpressionFilter<T, T2, T3, T4> AndIf(bool condition, Expression<Func<T, T2, T3, T4, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.AndAlso);
            }
            return this;
        }
        public static implicit operator Func<T, T2, T3, T4, bool>(ExpressionFilter<T, T2, T3, T4> filter)
        {
            return filter.Func;
        }
        public static implicit operator Expression<Func<T, T2, T3, T4, bool>>(ExpressionFilter<T, T2, T3, T4> filter)
        {
            return filter.Expressions;
        }
        private Expression<TT> Compose<TT>(Expression<TT> first, Expression<TT> second, Func<Expression, Expression, Expression> merge)
        {
            map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = Visit(second.Body);
            return Expression.Lambda<TT>(merge(first.Body, secondBody), first.Parameters);
        }
        protected override Expression VisitParameter(ParameterExpression p)
        {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement))
            {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }
    public class ExpressionFilter<T, T2, T3, T4, T5> : ExpressionVisitor
    {
        Expression<Func<T, T2, T3, T4, T5, bool>> _Filter;
        Dictionary<ParameterExpression, ParameterExpression> map;
        public ExpressionFilter(bool BaseFilter = true)
        {
            _Filter = (T, T2, T3, T4, T5) => BaseFilter;
        }
        Func<T, T2, T3, T4, T5, bool> Func
        {
            get { return _Filter.Compile(); }
            set { }
        }
        Expression<Func<T, T2, T3, T4, T5, bool>> Expressions
        {
            get { return _Filter; }
            set { }
        }

        public ExpressionFilter<T, T2, T3, T4, T5> Or(Expression<Func<T, T2, T3, T4, T5, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.OrElse);return this;

        }
        public ExpressionFilter<T, T2, T3, T4, T5> And(Expression<Func<T, T2, T3, T4, T5, bool>> expression)
        {
            _Filter = Compose(_Filter, expression, Expression.AndAlso); return this;
        }
        public ExpressionFilter<T, T2, T3, T4, T5> OrIf(bool condition, Expression<Func<T, T2, T3, T4, T5, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.OrElse);
            }
            return this;
        }
        public ExpressionFilter<T, T2, T3, T4, T5> AndIf(bool condition, Expression<Func<T, T2, T3, T4, T5, bool>> expression)
        {
            if (condition)
            {
                _Filter = Compose(_Filter, expression, Expression.AndAlso);
            }
            return this;
        }
        public static implicit operator Func<T, T2, T3, T4, T5, bool>(ExpressionFilter<T, T2, T3, T4, T5> filter)
        {
            return filter.Func;
        }
        public static implicit operator Expression<Func<T, T2, T3, T4, T5, bool>>(ExpressionFilter<T, T2, T3, T4, T5> filter)
        {
            return filter.Expressions;
        }
        private Expression<TT> Compose<TT>(Expression<TT> first, Expression<TT> second, Func<Expression, Expression, Expression> merge)
        {
            map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
            var secondBody = Visit(second.Body);
            return Expression.Lambda<TT>(merge(first.Body, secondBody), first.Parameters);
        }
        protected override Expression VisitParameter(ParameterExpression p)
        {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement))
            {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }

}
